import asyncio
import os
import re
from file_tool import move_file
from tidy_core.mapping import mapping


def file_collect(abs_dir_path,regexp_str, file_list,sep,sep_index,ext_list=None):
    sep_regexp = re.compile(sep)
    regexp = re.compile(regexp_str)
    selected_file_list = []
    i = 0
    if ext_list:
        def final_file_name_func(file_name):
            nonlocal i
            final_file_name = file_name + ext_list[i]
            i += 1
            return final_file_name
    else:
        def final_file_name_func(file_name):
            return file_name

    for file_name in file_list:
        sep_fix = sep_regexp.split(file_name)[sep_index]
        abs_file_path = os.path.join(abs_dir_path, file_name)

        if os.path.isfile(abs_file_path) and regexp.match(sep_fix):
            final_file_name = final_file_name_func(file_name)
            selected_file_list.append(final_file_name)

    return selected_file_list



async def tidy_up_async(config_dict):
    abs_dir_path = os.path.abspath(config_dict['dir_path'])
    file_list = os.listdir(abs_dir_path)
    file_ext_list = []

    move_task_list = []
    filter_dict = {}

    sep_index = 0
    match_rule_dict = {
        'is_head_match': config_dict['regexp:is_head_match'],
        'is_tail_match': config_dict['regexp:is_tail_match'],
        'is_line_match': config_dict['regexp:is_line_match']
    }

    if config_dict['classify:suffix']:
        file_list = [os.path.splitext(file_name)[0] for file_name in file_list]
        file_ext_list = [os.path.splitext(file_name)[1] for file_name in file_list]
        sep_index = -1

    if config_dict['is_exact']:
        regexp_condition_func = lambda sep_fix: sep_fix
    else:
        regexp_condition_func = lambda sep_fix: regexp_generator(sep_fix, **match_rule_dict)



    sep_regexp = re.compile(config_dict['sep'])


    i = -1

    for file_name in file_list:

        i += 1 #increment

        sep_fix = sep_regexp.split(file_name)[sep_index]
        match_key_str = regexp_condition_func(sep_fix)


        if filter_dict.get(match_key_str, False):
            continue

        filter_dict[match_key_str] = True

        prepared_file_collection = file_collect(abs_dir_path, file_list=file_list[i:], regexp_str=match_key_str,
                                                sep=config_dict['sep'], sep_index=sep_index, ext_list=file_ext_list)

        abs_dist_dir_path = os.path.join(abs_dir_path, sep_fix)



        if not os.path.exists(abs_dist_dir_path):
            os.mkdir(abs_dist_dir_path)


        for selected_file_name in prepared_file_collection:
            abs_file_path = os.path.join(abs_dir_path, selected_file_name)
            abs_dist_file_path = os.path.join(abs_dist_dir_path,selected_file_name)
            move_task = asyncio.create_task(move_file(abs_file_path, abs_dist_file_path))
            move_task_list.append(move_task)
        if move_task_list:
            await asyncio.wait(move_task_list)

    if config_dict['is_mapping']:
        await mapping(config_dict['mapping.path'], config_dict['mapping.source'], config_dict['mapping.is_outer'])

def regexp_generator(iterable_str, is_head_match = False, is_tail_match = False, is_line_match=False):
    regexp_str = ""
    match_dict = {"\\_":0,"\\-":0,"\\d":0,"[A-Za-z]":0,"\\.":0}
    ordered_match_list = ["\\_","\\-","\\d","[A-Za-z]","\\."]

    matched_list = []
    regexp_unit_list = []
    for char in iterable_str:
        for match_key in ordered_match_list:
            if re.match(match_key,char):
                if match_key not in matched_list:
                    matched_list.append(match_key)
                match_dict[match_key] += 1
                break


    for matched_key in matched_list:
        if match_dict[matched_key] < 2:
            regexp_unit_list.append(matched_key)
            continue
        regexp_unit_list.append(matched_key+'{'+str(match_dict[matched_key])+'}')
    if is_head_match:
        regexp_str += '^' + "".join(regexp_unit_list)

    elif is_tail_match:
        regexp_str +=  "".join(regexp_unit_list) + '$'

    elif is_line_match:
        regexp_str += '^'+ "".join(regexp_unit_list) + '$'

    return regexp_str








